package by.dkusch.aircompany.dao.impl;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.metamodel.SingularAttribute;

import org.hibernate.jpa.criteria.OrderImpl;
import org.springframework.stereotype.Repository;

import by.dkusch.aircompany.dao.CountryDao;
import by.dkusch.aircompany.model.filter.FilterCountry;
import by.dkusch.aircompany.model.filter.base.FilterEntity;
import by.dkusch.aircompany.model.tables.Country;
import by.dkusch.aircompany.model.tables.Country_;
import by.dkusch.aircompany.model.tables.base.BaseEntity_;

@Repository
public class CountryDaoImpl extends AbstractDaoImpl<Long, Country> implements CountryDao {

	public CountryDaoImpl() {
		super(Country.class);
	}

	@Override
	public List<Country> getAllItemsWithFilter(SingularAttribute<? super Country, ?> attr, boolean ascending, int startRecord, int pageSize, FilterEntity<Long, ? super Country> filter) {
		if (filter == null) {
			return getAllItems(attr, ascending, startRecord, pageSize);
		}

		CriteriaBuilder cBuilder = getEm().getCriteriaBuilder();

		CriteriaQuery<Country> criteria = cBuilder.createQuery(Country.class);
		Root<Country> fromCountry = criteria.from(Country.class);

		OrderImpl order = new OrderImpl(fromCountry.get(BaseEntity_.id), ascending);
		if (attr != null) {
			order = new OrderImpl(fromCountry.get(attr), ascending);
		}
		;
		List<Predicate> conditions = new ArrayList<Predicate>();

		FilterCountry fc = (FilterCountry) filter;

		if (fc.getCode() != null) {
			conditions.add(cBuilder.equal(cBuilder.upper(fromCountry.get(Country_.code)), fc.getCode().toUpperCase()));
		}

		if (fc.getName() != null) {
			conditions.add(cBuilder.like(cBuilder.upper(fromCountry.get(Country_.name)), fc.getName().toUpperCase()));
		}

		if (fc.getContinent() != null) {
			conditions.add(cBuilder.equal(cBuilder.upper(fromCountry.get(Country_.continent)), fc.getContinent().toUpperCase()));
		}

		TypedQuery<Country> query = getEm().createQuery(criteria.select(fromCountry).where(cBuilder.and(conditions.toArray(new Predicate[] {}))).orderBy(order));

		if (startRecord >= 0) {
			query.setFirstResult(startRecord);
			query.setMaxResults(pageSize);
		}

		List<Country> results = query.getResultList();
		return results;

	}

}
